/*
 * GtkPrinting.cs - Wordtrainer
 * 
 * Copyright (C) 1998-2007 Markus Kilås
 *               
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 *
 * Authors:
 *   Markus Kilås <markus@markuspage.com>
 * 
 */

//#define DEBUG_PRINT_LINES

using System;
using Gtk;
using Pango;
using Cairo;

namespace WtSharp
{
	
	
	public class GtkPrinting : Printing
	{
		private WtDocument m_document;
		private PageSettings m_settings;
		
		private const bool DEBUG_PRINT_LINES = false;
		
		/* Settings */
		private double headerHeight = 50;
		private double footerHeight = 30;
		private double bodyMargin = 20;
		
		/* BeginPrint calcs this */
		private Cairo.Rectangle headerRect;
		private Cairo.Rectangle bodyRect;
		private Cairo.Rectangle footerRect;
		private double bodyColumn1PosX;
		private double bodyColumn2PosX;
		private double lineHeight;
		private FontDescription bodyFontDesc;
		private int numWordsAtEachPage;
		private int currentWordIndex;
		
		public GtkPrinting()
		{
		}
		
		public void DoPrint(WtDocument document, PageSettings settings, Gtk.Window parent)
		{
			this.m_document = document;
			this.m_settings = settings;
			PrintOperation print = new PrintOperation();
		
			print.BeginPrint += BeginPrint;
			print.DrawPage += DrawPage;

			print.Run(PrintOperationAction.PrintDialog, parent);
		}
		
		private void BeginPrint(object sender, BeginPrintArgs args)
		{
			PrintOperation operation = (PrintOperation)sender;
			PrintContext context = args.Context;
			
			/* Header */
			this.headerRect = new Cairo.Rectangle(m_settings.MarginLeft, m_settings.MarginTop, context.Width-m_settings.MarginLeft-m_settings.MarginRight, headerHeight-m_settings.MarginTop);
			
			/* Body */
			this.bodyRect = new Cairo.Rectangle(m_settings.MarginLeft, m_settings.MarginTop+headerHeight+bodyMargin, context.Width-m_settings.MarginLeft-m_settings.MarginRight, context.Height-m_settings.MarginTop-headerHeight-footerHeight-2*bodyMargin-m_settings.MarginBottom);
			this.bodyFontDesc = FontDescription.FromString("sans "+m_settings.FontSize);
			this.bodyColumn1PosX = bodyRect.X;
			this.bodyColumn2PosX = bodyRect.X + bodyRect.Width / 2.0;
			
			// TODO: We need to find out the lineheight in order to know how many lines there are room for on 
			//       each page.
			//       What is done now is just assuming the height is 20 something:
			{
				this.lineHeight = 20; //TODO: Fix this
				//this.lineHeight = bodyFontDesc.
				//Gdk.Font font = Gdk.Font.FromDescription(bodyFontDesc);
				//Console.WriteLine("fontDescSize = "+bodyFontDesc.Size+" and scale is ");
				//Pango.Font font = context.PangoFontmap.LoadFont(context.CreatePangoContext(), bodyFontDesc);
				//Console.WriteLine("FontExtends-height: "+context.CairoContext.FontExtents.Height);
				/*Pango.Layout layout = context.CreatePangoLayout();
			      layout.FontDescription = bodyFontDesc;
			      layout.Width = context.Wi*/
			}			
			
			/* Footer */
			this.footerRect = new Cairo.Rectangle(m_settings.MarginLeft, context.Height-footerHeight-m_settings.MarginBottom, context.Width-m_settings.MarginLeft-m_settings.MarginRight, footerHeight);
			
			/* Number of pages */
			this.numWordsAtEachPage = (int)((bodyRect.Height - 3*lineHeight) / lineHeight);
			this.currentWordIndex = 0;
			int pages = (int)Math.Ceiling((double)m_document.Words.Count / (double)this.numWordsAtEachPage);
			if(pages < 1)
				operation.NPages = 1;
			else
				operation.NPages = pages;
		}
		
		
		private void DrawPage(object sender, DrawPageArgs args)
		{
			PrintOperation operation = (PrintOperation)sender;
			PrintContext context = args.Context;
			int page_nr = args.PageNr + 1;
			int num_pages = operation.NPages;
			Cairo.Context cr = context.CairoContext;
			Pango.Layout layout;
			
			
			/* Print Header: FileTitle */
			if(m_settings.PrintTitle)
			{
				layout = context.CreatePangoLayout();
				layout.SetText((string)m_document.Info["TITLE"]);   // TODO: How to set size of layout?
				layout.FontDescription = bodyFontDesc;
				cr.Color = new Cairo.Color(0, 0, 0);
				cr.MoveTo(headerRect.X, headerRect.Y);
				Pango.CairoHelper.LayoutPath(cr, layout);
				cr.Fill();
			}
			
			/* Print Header: Page x of y */
			if(m_settings.PrintPageNumber)
			{
				layout = context.CreatePangoLayout();
				layout.SetText("Page "+page_nr+" of "+num_pages);   // TODO: How to set size of layout?
				layout.FontDescription = bodyFontDesc;
				cr.Color = new Cairo.Color(0, 0, 0);
				cr.MoveTo(headerRect.X+headerRect.Width/2.0, headerRect.Y);  // TODO: Align right and to the right and relative to headerRect
				Pango.CairoHelper.LayoutPath(cr, layout);
				cr.Fill();
			}
			
			/* Rectangle to show header area */
#if DEBUG_PRINT_LINES
			{
				cr.SetSourceRGB(0.5, 1, 0.5);
				cr.Rectangle(headerRect);
				cr.LineWidth = 1;
				cr.Stroke();
			}
#endif
			
			
			int currentLine = 1;
			
			/* Rectangle to show body area */
#if DEBUG_PRINT_LINES
			{
				cr.SetSourceRGB(0.5, 1, 0.5);
				cr.Rectangle(bodyRect);
				cr.LineWidth = 1;
				cr.Stroke();
			}
#endif
						
			/* Write titles */
			cr.Color = new Cairo.Color(0, 0, 0);
			
			if(m_settings.PrintWords == PageSettings.PrintWordsType.OnlyT) // Both titles but "translation" first
			{
				// Translation title
				layout = context.CreatePangoLayout();
				layout.SetText(m_document.TitleTranslation);   // TODO: How to set size of layout?
				layout.FontDescription = bodyFontDesc;
				cr.MoveTo(bodyColumn1PosX, bodyRect.Y+lineHeight*currentLine);
				Pango.CairoHelper.LayoutPath(cr, layout);
				cr.Fill();
				
				// Forign word title
				layout = context.CreatePangoLayout();
				layout.SetText(m_document.TitleForeign);   // TODO: How to set size of layout?
				layout.FontDescription = bodyFontDesc;
				cr.MoveTo(bodyColumn2PosX, bodyRect.Y+lineHeight*currentLine);
				Pango.CairoHelper.LayoutPath(cr, layout);
				cr.Fill();
			}
			else  // Both titles : the default one
			{
				// Forign word title
				layout = context.CreatePangoLayout();
				layout.SetText(m_document.TitleForeign);   // TODO: How to set size of layout?
				layout.FontDescription = bodyFontDesc;
				cr.MoveTo(bodyColumn1PosX, bodyRect.Y+lineHeight*currentLine);
				Pango.CairoHelper.LayoutPath(cr, layout);
				cr.Fill();
				
				// Translation title
				layout = context.CreatePangoLayout();
				layout.SetText(m_document.TitleTranslation);   // TODO: How to set size of layout?
				layout.FontDescription = bodyFontDesc;
				cr.MoveTo(bodyColumn2PosX, bodyRect.Y+lineHeight*currentLine);
				Pango.CairoHelper.LayoutPath(cr, layout);
				cr.Fill();
			}
			
			//Console.WriteLine("lineCount:"+layout.LineCount);
			//Console.WriteLine("width:"+layout.Width);
			
			currentLine += 2;
			
			for(int j = 0; j < this.numWordsAtEachPage && currentWordIndex < m_document.Words.Count; currentWordIndex++,j++)
			{
				WtWord word = (WtWord)m_document.Words[currentWordIndex];
				
				switch(m_settings.PrintWords)
				{
				case PageSettings.PrintWordsType.OnlyF:
				
					// Forign word
					layout = context.CreatePangoLayout();
					layout.SetText(word.WordF);   // TODO: How to set size of layout?
					layout.FontDescription = bodyFontDesc;
					cr.MoveTo(bodyColumn1PosX, bodyRect.Y+lineHeight*currentLine);
					Pango.CairoHelper.LayoutPath(cr, layout);
					cr.Fill();
					
					break;
					
				case PageSettings.PrintWordsType.OnlyT:	
				
					// Translation
					layout = context.CreatePangoLayout();
					layout.SetText(word.WordT);   // TODO: How to set size of layout?
					layout.FontDescription = bodyFontDesc;
					cr.MoveTo(bodyColumn1PosX, bodyRect.Y+lineHeight*currentLine);
					Pango.CairoHelper.LayoutPath(cr, layout);
					cr.Fill();
					
					break;
				default:
					
					// Forign word
					layout = context.CreatePangoLayout();
					layout.SetText(word.WordF);   // TODO: How to set size of layout?
					layout.FontDescription = bodyFontDesc;
					cr.MoveTo(bodyColumn1PosX, bodyRect.Y+lineHeight*currentLine);
					Pango.CairoHelper.LayoutPath(cr, layout);
					cr.Fill();
					
					// Translation
					layout = context.CreatePangoLayout();
					layout.SetText(word.WordT);   // TODO: How to set size of layout?
					layout.FontDescription = bodyFontDesc;
					cr.MoveTo(bodyColumn2PosX, bodyRect.Y+lineHeight*currentLine);
					Pango.CairoHelper.LayoutPath(cr, layout);
					cr.Fill();
				
					break;
				}
				
				currentLine++;
			}
			
			/* Rectangle to show footer area */
#if DEBUG_PRINT_LINES
			{
				cr.SetSourceRGB(0.5, 1, 0.5);
				cr.Rectangle(footerRect);
				cr.LineWidth = 1;
				cr.Stroke();
			}
#endif
			
			/* Print footer */
			layout = context.CreatePangoLayout();
			layout.SetText("www.wordtrainer.net");   // TODO: How to set size of layout?
			layout.FontDescription = bodyFontDesc;
			cr.Color = new Cairo.Color(0, 0, 0);
			cr.MoveTo(footerRect.X, footerRect.Y);
			Pango.CairoHelper.LayoutPath(cr, layout);
			cr.Fill();
		}

	}
}
